package com.pan.games.threadgame.communicate;

/**
 * @author by panstark
 * @description
 * @notice
 * @date 2020/12/15
 */
public class JoinWaitNotify {

    private static Object tool = new Object();


    public static void main(String[] args) throws InterruptedException {

        //join方法示例
        letsJoin();

        //wait 和 notify方法示例
        waitAndNofity();

        System.out.println("主线程执行完毕。");
    }

    public static void letsJoin() throws InterruptedException {
        JoinWaitNotifyWorker worker = new JoinWaitNotifyWorker();
        Thread threadA = new Thread(worker);
        Thread threadB = new Thread(worker);

        threadA.start();
        //threadA join之后，主线程将会等待threadA执行完毕，再往下进行
        threadA.join();
        threadB.start();
        threadB.join();
        System.out.println("两个线程都执行完毕了");
    }

    /**
     *
     * 1、通过构造器进行传参
     * 2、通过属性传参
     * 3、通过回调函数传递数据
     * 注意： wait和 notify必须配合synchronized使用，wait方法释放锁，notify方法不释放锁
     *
     */
    public static void waitAndNofity(){

        JoinWaitNotifyWaitWorker waithWorker = new JoinWaitNotifyWaitWorker(tool);
        JoinWaitNotifyNoticeWorker noticeWorker = new JoinWaitNotifyNoticeWorker(tool);

        Thread threadA = new Thread(waithWorker);
        Thread threadC = new Thread(waithWorker);
        Thread threadD = new Thread(waithWorker);
        Thread threadE = new Thread(waithWorker);

        //注意thread用的是notify则只会随机唤醒一个线程，如果用的是notifyAll则可以唤醒所有线程
        Thread threadB = new Thread(noticeWorker);

        threadA.start();
        threadB.start();
        threadC.start();
        threadD.start();
        threadE.start();

    }

}



class JoinWaitNotifyWaitWorker implements Runnable{

    private Object tool;
    public JoinWaitNotifyWaitWorker(){

    }

    public JoinWaitNotifyWaitWorker(Object tool){
        this.tool = tool;
    }

    @Override
    public void run() {
        for(int i=0;i<10;i++){
            synchronized (tool){

                try {
                    Thread.sleep(300);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (i == 1){
                    try {
                        tool.wait();// 当线程执行到1的时候，进行等待
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

            }
            System.out.println(Thread.currentThread().getName()+ " outer is running:"+i);

        }
    }
}

class JoinWaitNotifyNoticeWorker implements Runnable{

    private Object tool;
    public JoinWaitNotifyNoticeWorker(){

    }

    public JoinWaitNotifyNoticeWorker(Object tool){
        this.tool = tool;
    }

    @Override
    public void run() {
        for(int i=0;i<10;i++){

            synchronized (tool){
                try {
                    Thread.sleep(300);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (i == 5){
                    tool.notify();// 唤醒一个线程
                }
                if(i==9){
                    tool.notifyAll();//唤醒所有的线程
                }
            }
            System.out.println(Thread.currentThread().getName()+ " outer is running:"+i);
        }
    }
}

class JoinWaitNotifyWorker implements Runnable{

    @Override
    public void run() {

        for(int i=0;i<10;i++){
            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+ " is running:"+i);
        }

    }
}
